package com.youpai.platform.chat.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.youpai.platform.chat.service.entity.po.ChatAccountPO;
import com.youpai.platform.chat.service.entity.po.ChatMessagePO;
import com.youpai.platform.chat.service.entity.po.ChatSessionPO;
import com.youpai.platform.chat.service.mapper.ChatAccountMapper;
import com.youpai.platform.chat.service.mapper.ChatMessageMapper;
import com.youpai.platform.chat.service.mapper.ChatSessionMapper;
import com.youpai.platform.chat.service.service.ChatPageService;
import com.youpai.platform.chat.service.util.ChatUtils;
import com.youpai.platform.chat.web.entity.req.GetChatDetailPageReq;
import com.youpai.platform.chat.web.entity.resp.GetChatDetailPageResp;
import com.youpai.platform.common.enums.ProcessCodeEnum;
import com.youpai.platform.common.exceptions.BaseBizException;
import com.youpai.platform.common.exceptions.BaseParamException;
import com.youpai.platform.common.util.UserContext;
import com.youpai.platform.user.service.biz.UserActiveBizService;
import com.youpai.platform.user.service.entity.dto.UserActiveDTO;
import com.youpai.platform.user.service.entity.po.UserPO;
import com.youpai.platform.user.service.mapper.UserMapper;
import com.youpai.platform.vulture.common.enums.AppIdEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.assertj.core.util.Lists;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @date: 2022/7/23 16:47
 * @author: Anna
 * @version: 1.0
 * @description: 聊天页service
 */
@Slf4j
@Component
public class ChatPageServiceImpl implements ChatPageService {

    @Resource
    private ChatSessionMapper chatSessionMapper;
    @Resource
    private ChatAccountMapper chatAccountMapper;
    @Resource
    private UserActiveBizService userActiveBizService;
    @Resource
    private ChatMessageMapper chatMessageMapper;
    @Resource
    private UserMapper userMapper;

    @Override
    public GetChatDetailPageResp getChatDetailPage(GetChatDetailPageReq req) {
        String toAccId = ChatUtils.buildAccId(AppIdEnum.KILA.appId, req.getToUid());
        // 获取聊天账号信息
        ChatAccountPO chatAccount = getChatAccount(toAccId);
        if (null == chatAccount) {
            log.error("用户不存在:{}", req.getToUid());
            throw new BaseParamException(ProcessCodeEnum.USER_NOT_EXIST);
        }
        String toUid = chatAccount.getUid();
        // 获取用户活跃信息
        UserActiveDTO userActive = getUserActive(toUid);
        if (null == UserContext.getUserContext()) {
            throw new BaseBizException(ProcessCodeEnum.TOKEN_FAILURE);
        }
        // 获取用户基本信息
        String uid = UserContext.getUserContext().getUid();
        Map<Long, UserPO> userMap = queryUser(uid, toUid);
        GetChatDetailPageResp resp = buildGetChatDetailPageResp(userMap, userActive);
        ChatSessionPO chatSessionPO = createSession(ChatUtils.getAccIdByUidAndAppId(uid, AppIdEnum.KILA.appId), toAccId);
        resp.setLastMsgId(chatSessionPO.getLastMsgId());
        resp.setSessionId(chatSessionPO.getSessionId());
        return resp;

    }

    private ChatSessionPO createSession(String fromAccId, String toAccId) {

        ChatSessionPO chatSessionPO = new ChatSessionPO();
        chatSessionPO.setSessionId(ChatUtils.buildSessionId(fromAccId, toAccId))
                .setAccId(fromAccId);
        try {
            chatSessionMapper.insert(chatSessionPO);
        } catch (DuplicateKeyException duplicateKeyException) {
            log.warn("会话已存在");
            LambdaQueryWrapper<ChatMessagePO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ChatMessagePO::getSessionId, chatSessionPO.getSessionId())
                    .orderByDesc(ChatMessagePO::getMessageId)
                    .last("limit 1");
            ChatMessagePO chatMessagePO = chatMessageMapper.selectOne(queryWrapper);
            chatSessionPO.setLastMsgId(chatMessagePO == null ? 0 : chatMessagePO.getMessageId());
        }
        return chatSessionPO;
    }

    private GetChatDetailPageResp buildGetChatDetailPageResp(Map<Long, UserPO> userMap, UserActiveDTO userActive) {
        Long fromUid = Long.valueOf(UserContext.getUserContext().getUid());
        Long toUid = userActive.getUid();
        UserPO fromUser = userMap.get(fromUid);
        UserPO toUser = userMap.get(toUid);
        GetChatDetailPageResp resp = new GetChatDetailPageResp();
        resp.setFromUid(fromUid.toString())
                .setFromUserAvatar(fromUser.getAvatar())
                .setFromUserNickName(fromUser.getNickName())
                .setToUid(toUid.toString())
                .setToAccId(ChatUtils.buildAccId(AppIdEnum.KILA.appId, toUid.toString()))
                .setToUserAvatar(toUser.getAvatar())
                .setToUserNickName(toUser.getNickName())
                .setToUserState((userActive.getUserState() > 1) ? 1 : userActive.getUserState())
                .setToUserStateTag(userActive.getUserStateTag());
        return resp;
    }

    private Map<Long, UserPO> queryUser(String... uids) {
        if (null == uids || uids.length == 0) {
            return new HashMap<>();
        }
        LambdaQueryWrapper<UserPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(UserPO::getUid, Lists.list(uids));
        List<UserPO> userPOList = userMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(userPOList)) {
            return new HashMap<>();
        }
        return userPOList.stream().collect(Collectors.toMap(UserPO::getUid, Function.identity(), (key1, key2) -> key2));
    }

    private UserActiveDTO getUserActive(String uid) {
        Map<Long, UserActiveDTO> userActiveDTOMap = userActiveBizService.queryUserActive(Lists.list(Long.valueOf(uid)));
        if (null == userActiveDTOMap) {
            return new UserActiveDTO();
        }
        return userActiveDTOMap.get(Long.valueOf(uid));
    }

    private ChatAccountPO getChatAccount(String accId) {
        LambdaQueryWrapper<ChatAccountPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatAccountPO::getAccId, accId);
        return chatAccountMapper.selectOne(queryWrapper);
    }
}
